#include "Tile.h"
#include "BaseInterface.h"
#include "Item.h"
#include "AnimationManager.h"
#include "Animation.h"
#include "BaseAI.h"
#pragma once

enum Actions { ATK = -1, ITEM, ABILITY };
enum abilities {REINFORCED_CARDBOARD,SHIELD_BASH,COVER,HIDE,BACKSTAB,INFLICT_ALLERGIES,LIGHTNING_BOLT,FIRE_BALLS,TSUNAMI,PEROXIDE,MULTI_SHOT,SHOOT_HARDER,SHOOT_FARTHER,TAUNT,BITE_KNEE_CAPS,GUARD_BRIDGE,GUARD,MOVE2,ATTACK2,HPOTION2,MPOTION2,INHALER2};
enum EffectTypes {REINFORCED,HIDDEN,ALLERGIES,COVERED,TAUNTED,GUARDING,GUARDING_BRIDGE,KNEE_CAPS,MOVEMENT,DEFENSE,ATTACK,RANGE,SPEED,AGILITY,STAMINA,LAVA_DAMAGE};

struct StatusEffect
{
	int effectType;
	int effectValue;
	int turnsLeft;
	BaseCharacter * creator;
};

class BaseCharacter : public BaseInterface
{
public:
	struct AnimationInfo
	{
		int currentFrame;
		int currentAnimation;
		float fTimeWaited;
		float fScale;
		bool bIsFlipped;
		int Increment;
		int prevState;
		bool IsPlaying;
		bool Dead;
	};


	


private:

	bool hasMoved;
	bool usedAction;
	bool playerCharacter;
	bool isDead;
	int HP;
	int HPMax;
	int MP;
	int MPMax;
	int attack;
	int defense;
	int speed;
	int agility;
	int moveRange;
	int range;
	int stamina;
	int weapon;
	char* wpnName;
	char* armName;
	int armor;
	int experience;
	int level;
	bool changedState;
	
	unsigned int references;
	AnimationInfo AInfo;
	AnimationManager* AniMan;
	vector<Animation*> AniVec;
	vector<StatusEffect*> statusEffects;
	vector<StatusEffect*> tileEffects;

	// int for facing direction
	// 0 for up, 1 for right,2 for down,3 for left
	int facingDirection;


protected:
	int type;
	int hpGain;
	int mpGain;
	int atkGain;
	int defGain;
	int spdGain;
	int agiGain;
	int stmGain;
	Tile * currentTile;
	BaseAI * currAI;
	bool dying;

public:
	BaseCharacter(void);
	virtual ~BaseCharacter(void)=0;
	bool Move(Tile * target, int state=0);
	bool Attack(Tile * target, int state = 0);
	void Defend();
	void CalculateExp(BaseCharacter* pUser, BaseCharacter* pTarget = nullptr, int type = -1, int amt = 0); // Calculates the amount of experience based on the amount of damage/healing the user has done
																							// then uses the levels of the user and the target to modify the exp amount.
	void LevelUp(void);
	bool UseItem(Item * selectedItem);
	bool UseAbility(int abilityID,Tile * target, int state=0);
	virtual void Update(float elapsedTime);
	virtual void Render();
	
	void ChangeState(int state) { AInfo.prevState = AInfo.currentAnimation; AInfo.currentAnimation = state; AInfo.currentFrame = 0; changedState = true;}

	void AddRef(void) {references++;}
	void Release(void) {references--;  if(references <=0) delete this;}

	// Accessors
	AnimationInfo* GetAnimInfo(void) {return &AInfo;}
	Tile* GetTile(void) {return currentTile;}
	int GetHP(void)					const	{ return HP; }
	int GetMaxHP(void)				const	{ return HPMax; }
	int GetMP(void)					const	{ return MP; }
	int GetMaxMP(void)				const	{ return MPMax; }
	int GetAtk(void)				const	{ return attack; }
	int GetDef(void)				const	{ return defense; }
	int GetSpd(void)				const	{ return speed; }
	int GetAgi(void)				const	{ return agility; }
	int GetSta(void)				const	{ return stamina; }
	int GetMov(void)				const	{ return moveRange; }
	int GetRng(void)				const	{ return range; }
	int GetType(void)				const	{ return type; }
	int GetWpn(void)				const	{ return weapon; }
	char* GetWpnName(void)			const	{ return wpnName; }
	char* GetArmName(void)			const	{ return armName; }
	int GetArm(void)				const	{ return armor; }
	int GetExp(void)				const	{ return experience; }
	unsigned int GetLevel(void)		const	{ return level; }
	int GetFacing()					const	{ return facingDirection; }

	bool IsPlayer(void)				const	{ return playerCharacter; }
	bool HasMoved(void)				const	{ return hasMoved; }
	bool UsedAction(void)			const	{ return usedAction; }
	bool IsDead(void)				const	{ return isDead; }

	// Mutators
	void SetHP(int val)						{ HP = val; }
	void SetMaxHP(int val)					{ HPMax = val; }
	void SetMP(int val)						{ MP = val; }
	void SetMaxMP(int val)					{ MPMax = val; }
	void SetAtk(int val)					{ attack = val; }
	void SetDef(int val)					{ defense = val; }
	void SetSpd(int val)					{ speed = val; }
	void SetAgi(int val)					{ agility = val; }
	void SetSta(int val)					{ stamina = val; }
	void SetMov(int val)					{ moveRange = val; }
	void SetRng(int val)					{ range = val; }
	void SetWpn(int val)					{ weapon = val; }
	void SetWpnName(char* name);
	void SetArmName(char* name);
	void SetArm(int val)					{ armor = val; }
	void SetExp(int exp)					{ experience = exp; }
	void SetLevel(unsigned int lvl)			{ level = lvl; }

	void SetPlayer(bool val)				{ playerCharacter = val; }
	void SetMoved(bool val)					{ hasMoved = val; }
	void SetActed(bool val)					{ usedAction = val; }
	void SetTile(Tile* t);					
	void SetDead(bool val)					{ isDead = val; }
	void SetFacing(int i)					{ this->facingDirection = i;}

	vector<StatusEffect*> * GetStatusEffects()
	{
		return &statusEffects;
	}

	vector<StatusEffect*> * GetTileEffects()
	{
		return &tileEffects;
	}

	// updates all statuseffects on character
	// call for each character at the start of a new turn(both player and ai turns)
	void UpdateStatusEffects();

	BaseAI * GetAI()
	{
		return this->currAI;
	}

	

};

